<template>
  <el-form ref="FormRef" :model="searchForm" :rules="rules" class="filter-bar" @submit.prevent>
    <div class="filter-wrapper">
      <el-row :gutter="24">
        <el-col v-for="(item,index) in source" :key="index" :span="item.span || 8">
          <el-form-item :label="item.label" :prop="item.prop" :label-width="item.width || '100px'">
            <FilterItemInput
              :disabled="item.isDisabled"
              v-model="searchForm[item.prop]"
              :type="item.type"
              :multiple="item.multiple"
              :filterable="item.filterable"
              :controlsPosition="item.controlsPosition"
              :input-props="item.inputProps"
              :suffix-icon="item.suffixIcon"
              :icon="item.icon"
              @change="(val)=>handleEvents(val,'change',item)"
              @click="(val)=>handleEvents(val,'click',item)"
              @beforeUpload="beforeUpload"
            />
            <span v-if="item.remark">{{ item.remark }}</span>
          </el-form-item>
        </el-col>
      </el-row>
      <FilterButtonGroup
        :is-collapse="isCollapse"
        :is-toggle="isToggle"
        :hasButton="hasButton"
        :hasTableButton="hasTableButton"
        @on-search="onSearch"
        @on-reset="onReset"
      />
    </div>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive, ref, toRaw, watchEffect } from 'vue'
import FilterItemInput from '@/components/FilterBar/components/filter-item-input.vue'
import FilterButtonGroup from '@/components/FilterBar/components/filter-button-group.vue'
import type { FilterItem, FieldsItemType } from '@/components/FilterBar/types'
import type { FormInstance, FormRules } from 'element-plus'
// 7-17增加hasButton属性用于layoutcard窗口中确认  取消按钮的显示和隐藏;
const props = defineProps<{
  filters: FilterItem[], hasButton: hasButton, multiple: multiple, filterable?: filterable, icon: icon
  hasTableButton: hasTableButton, modelValue: modelValue, rules?: any
}>()
const emits = defineEmits(['search-change', 'search-reset'])

const offset = ref(0)
const isCollapse = ref(false)
const source = ref(props.filters.slice(0))

const isToggle = true
const models = props.filters.reduce((previous, current) => {
  return Object.assign(previous, { [current.prop]: current.defaultValue })
}, {})
const searchForm = reactive<FieldsItemType>(models)
const FormRef = ref<FormInstance>()

const getParams = () => {
  const data = toRaw(searchForm)
  return Object.keys(data).reduce((pre, cur) => {
    return Object.assign(pre, { [cur]: data[cur] || undefined })
  }, {})
}

// 7-28增加upload相关方法
const beforeUpload = (rawFile) => {
  emits('beforeUpload', rawFile)
}
/**
 * 点击查询
 */
const onSearch = () => {
  emits('search-change', getParams())
}

/**
 * 点击重置按钮
 */
const onReset = () => {
  console.log(searchForm)
  FormRef.value?.resetFields()
  props.filters.forEach(v => {
    searchForm[v.prop] = v.defaultValue
  })
  emits('search-reset', getParams())
}

// ========更新字段及数据源API
const handleEvents = (value: string, event: string, itr: FilterItem) => {
  const functions = itr.events?.[event]
  if (functions) {
    const func = {
      setFieldsValue,
      setOptions
    }
    functions(value, func)
  }
}
const setFieldsValue = (data: FieldsItemType) => {
  Object.keys(data).forEach(key => {
    searchForm[key] = data[key]
  })
}
const setOptions = (key: string, data: []) => {
  source.value.forEach(col => {
    if (col.prop === key && col.inputProps) {
      col.inputProps.options = data
    }
  })
}

watchEffect(() => {
  const length = source.value.length
  if (length % 3 === 0) {
    offset.value = 16
  } else if (length % 3 === 1) {
    offset.value = 8
  } else {
    offset.value = 0
  }
})
// 子组件定义验证方法
const validateRuleFormRef = async () => {
  // 校验成功则方法自动返回true，校验方法报错则说明校验失败，返回false
  try {
    return await FormRef.value.validate()
  } catch (error) {
    return false
  }
}
// 将方法暴露出去
defineExpose({
  setFieldsValue,
  setOptions,
  getParams,
  validateRuleFormRef
})
</script>

<style lang="less" scoped>
.filter-bar {
  .filter-wrapper {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    >.el-row {
      flex: 1;
    }
  }
  :deep(.el-col) {
    padding-right: 16px !important;
  }
  .el-form-item {
    width: 100%;
    margin-bottom: 24px;
    :deep(.el-form-item__label) {
      min-width: 68px;
    }
    .only-one {
      width: 260px!important;
    }
  }
}
</style>
